import _ from "lodash"
import Vue, { PluginObject } from "vue"
import SocketIO from 'socket.io-client'

declare module 'vue/types/vue' {
    interface Vue {
        /** websocket 通讯 */
        $socket: SocketIOClient.Socket;
        $socketHelper: SocketIOHelper;
    }
    interface VueConstructor {
        /** websocket 通讯 */
        $socket: SocketIOClient.Socket;
        $socketHelper: SocketIOHelper;
    }
}

class SocketIOHelper {
    private $socket: SocketIOClient.Socket;
    constructor(_socket: SocketIOClient.Socket) {
        this.$socket = _socket;
    }

    api<Tresult>(
        event: string | { event: string, ret_event?: string },
        payload?: any
    ): Promise<Tresult> {
        let event_key = _.isString(event) ? event : event.event;
        let ret_event_key = _.isString(event)
            ? event + "-ret"
            : (event.ret_event || event.event + "-ret");
        return new Promise<Tresult>((resolve, reject) => {
            this.$socket.once(ret_event_key, resolve);
            this.$socket.emit(event_key, payload);
        });
    }
}

class SocketIOInstall implements PluginObject<string>{
    install(vue: typeof Vue, url?: string) {
        if (url) {
            let socket = SocketIO(url);
            let socket_helper = new SocketIOHelper(socket);

            Object.defineProperty(Vue, '$socket', { value: socket, writable: false });
            Object.defineProperty(vue.prototype, '$socket', { value: socket, writable: false });

            Object.defineProperty(Vue, '$socketHelper', { value: socket_helper, writable: false });
            Object.defineProperty(vue.prototype, '$socketHelper', { value: socket_helper, writable: false });
        } else {
            console.log("必须输入 websocket 的连接地址！");
        }
    }
}

export default new SocketIOInstall;